package com.atguigu.tingshu.search.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
import co.elastic.clients.elasticsearch._types.aggregations.Buckets;
import co.elastic.clients.elasticsearch._types.aggregations.LongTermsBucket;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.NestedQuery;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.CompletionSuggestOption;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.Suggestion;
import co.elastic.clients.json.JsonData;
import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.album.AlbumFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.model.album.*;
import com.atguigu.tingshu.model.search.AlbumInfoIndex;
import com.atguigu.tingshu.model.search.AttributeValueIndex;
import com.atguigu.tingshu.model.search.SuggestIndex;
import com.atguigu.tingshu.query.search.AlbumIndexQuery;
import com.atguigu.tingshu.search.repository.AlbumInfoIndexRepository;
import com.atguigu.tingshu.search.repository.SuggestIndexRepository;
import com.atguigu.tingshu.search.service.SearchService;
import com.atguigu.tingshu.user.client.UserFeignClient;
import com.atguigu.tingshu.vo.search.AlbumInfoIndexVo;
import com.atguigu.tingshu.vo.search.AlbumSearchResponseVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import jodd.util.StringUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.suggest.Completion;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import cn.hutool.core.lang.Assert;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


@Slf4j
@Service
@SuppressWarnings({"all"})
public class SearchServiceImpl implements SearchService {


    @Autowired
    private AlbumInfoIndexRepository albumInfoIndexRepository;

    @Autowired
    private SuggestIndexRepository suggestIndexRepository;

    @Autowired
    private AlbumFeignClient albumFeignClient;

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    @Autowired
    private RedisTemplate redisTemplate;

    public static final String INDEX_NAME = "albuminfo";
    public static final String SUGGEST_INDEX_NAME = "suggestinfo";

    /**
     * 上架专辑索引,涉及 albumInfo 表 album_attribute_value 表 album_stat 表 并且需要查询出 userNickName
     * 需要远程调用 service-album-client service-user-client
     *
     * @param albumId
     */
    @Override
    public void upperAlbumInfoIndex(Long albumId) {
        AlbumInfoIndex albumInfoIndex = new AlbumInfoIndex();
        // 1.查询专辑信息并拷贝给 albumInfoIndex
        CompletableFuture<AlbumInfo> albumInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            AlbumInfo albumInfo = albumFeignClient.getAlbumInfo(albumId).getData();
            Assert.notNull(albumInfo, "专辑不存在，专辑ID{}", albumId);
            BeanUtils.copyProperties(albumInfo, albumInfoIndex);
            return albumInfo;
        }, threadPoolExecutor);
        // 2.albumInfo 中获取 userId , 获取 userNickName
        CompletableFuture<Void> userNickNameCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            UserInfoVo userInfoVo = userFeignClient.getUserInfoVo(albumInfo.getUserId()).getData();
            if (userInfoVo != null) {
                albumInfoIndex.setAnnouncerName(userInfoVo.getNickname());
            }
        }, threadPoolExecutor);
        // 3.albumInfo 中获取 category3Id，并获取 category1Id、category2Id
        CompletableFuture<Void> categoryIdsCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            BaseCategoryView baseCategoryView = albumFeignClient.getCategoryView(albumInfo.getCategory3Id()).getData();
            albumInfoIndex.setCategory1Id(baseCategoryView.getCategory1Id());
            albumInfoIndex.setCategory2Id(baseCategoryView.getCategory2Id());
        }, threadPoolExecutor);
        // 4.根据 albumId 查询 album_attribute_value 表
        CompletableFuture<Void> attributeValueIndexListCompletableFuture = CompletableFuture.runAsync(() -> {
            List<AlbumAttributeValue> list = albumFeignClient.findAlbumAttributeValue(albumId).getData();
            if (CollectionUtil.isNotEmpty(list)) {
                List<AttributeValueIndex> attributeValueIndexList = list.stream().map(albumAttributeValue -> {

                    AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
                    attributeValueIndex.setAttributeId(albumAttributeValue.getAttributeId());
                    attributeValueIndex.setValueId(albumAttributeValue.getValueId());
                    return attributeValueIndex;
                }).collect(Collectors.toList());
                albumInfoIndex.setAttributeValueIndexList(attributeValueIndexList);
            }
            return;
        }, threadPoolExecutor);

        //5.封装统计信息，采用产生随机值 以及专辑热度
        CompletableFuture<Void> statCompletableFuture = CompletableFuture.runAsync(() -> {
            //5.1 随机为专辑产生播放量，订阅量，购买量，评论量
            int num1 = RandomUtil.randomInt(1000, 2000);
            int num2 = RandomUtil.randomInt(500, 1000);
            int num3 = RandomUtil.randomInt(200, 400);
            int num4 = RandomUtil.randomInt(100, 200);
            albumInfoIndex.setPlayStatNum(num1);
            albumInfoIndex.setSubscribeStatNum(num2);
            albumInfoIndex.setBuyStatNum(num3);
            albumInfoIndex.setCommentStatNum(num4);

            //5.2 基于统计值计算出专辑得分 为不同统计类型设置不同权重
            BigDecimal bigDecimal1 = new BigDecimal(num4).multiply(new BigDecimal("0.4"));
            BigDecimal bigDecimal2 = new BigDecimal(num3).multiply(new BigDecimal("0.3"));
            BigDecimal bigDecimal3 = new BigDecimal(num2).multiply(new BigDecimal("0.2"));
            BigDecimal bigDecimal4 = new BigDecimal(num1).multiply(new BigDecimal("0.1"));
            BigDecimal hotScore = bigDecimal1.add(bigDecimal2).add(bigDecimal3).add(bigDecimal4);
            albumInfoIndex.setHotScore(hotScore.doubleValue());
        }, threadPoolExecutor);
        // 6.等待所有任务执行完成
        CompletableFuture.allOf(
                albumInfoCompletableFuture,
                userNickNameCompletableFuture,
                categoryIdsCompletableFuture,
                attributeValueIndexListCompletableFuture,
                statCompletableFuture
        ).join();

        // 调用 Spring Data Elasticsearch 的 save 方法
        albumInfoIndexRepository.save(albumInfoIndex);

        this.saveSuggetIndex(albumInfoIndex);


    }

    @Override
    public void saveSuggetIndex(AlbumInfoIndex albumInfoIndex) {
        // 封装suggestIndex对象并保存至ES中
        SuggestIndex suggestIndex = new SuggestIndex();
        suggestIndex.setId(albumInfoIndex.getId());
        String title = albumInfoIndex.getAlbumTitle();
        suggestIndex.setTitle(title);
        suggestIndex.setKeyword(new Completion(new String[]{suggestIndex.getTitle()}));
        suggestIndex.setKeywordPinyin(new Completion(new String[]{PinyinUtil.getPinyin(title, "")}));
        suggestIndex.setKeywordSequence(new Completion(new String[]{PinyinUtil.getFirstLetter(title, "")}));
        // 保存至ES中
        suggestIndexRepository.save(suggestIndex);
    }




    /**
     * 根据 albumId 删除专辑索引
     *
     * @param albumId
     */
    @Override
    public void lowerAlbumInfoIndex(Long albumId) {
        albumInfoIndexRepository.deleteById(albumId);
    }

    /**
     * 关键词搜索，重点：ES查询参数转化、ES查询结果转化
     * @param albumIndexQuery
     * @return
     */
    @Override
    @SneakyThrows
    public AlbumSearchResponseVo albumInfo(AlbumIndexQuery albumIndexQuery) {

        AlbumSearchResponseVo albumSearchResponseVo = new AlbumSearchResponseVo();
        // 1.封装查询参数
        SearchRequest searchRequest = this.queryParams(albumIndexQuery);
        // System.err.println(searchRequest.toString());
        // 2.在ES中查询
        SearchResponse<AlbumInfoIndex> albumInfoIndexSearchResponse = elasticsearchClient.search(searchRequest, AlbumInfoIndex.class);
        // 3.将查询结果转化为AlbumSearchResponseVo
        albumSearchResponseVo = this.parseResult(albumInfoIndexSearchResponse,albumIndexQuery);


        return albumSearchResponseVo;
    }

    /**
     * 查询指定一级分类下热门排行专辑 ES站内搜索
     * @param category1Id
     * @return
     */
    @Override
    @SneakyThrows
    public List<Map<String, Object>> albumInfoChannel(Long category1Id) {
        // 获取一级分类下热门排行专辑
        List<BaseCategory3> baseCategory3List = albumFeignClient.findTopBaseCategory3(category1Id).getData();
        Assert.notNull(baseCategory3List, "一级分类{}未包含置顶三级分类", category1Id);
        //1.2 获取所有置顶三级分类ID集合
        List<Long> baseCategory3IdList = baseCategory3List.stream().map(BaseCategory3::getId).collect(Collectors.toList());
        //1.3 将三级分类集合转为Map<三级分类ID，三级分类对象> 方便解析结果封装三级分类对象
        //对BaseCategory3集合处理，转为Map Map中Key:ID，Map中val:三级分类对象BaseCategory3
        Map<Long, BaseCategory3> category3Map = baseCategory3List.stream()
                .collect(Collectors.toMap(BaseCategory3::getId, baseCategory3 -> baseCategory3));
        //1.4 将置顶三级分类ID转为FieldValue类型
        List<FieldValue> fieldValueList = baseCategory3IdList.stream()
                .map(baseCategory3Id -> FieldValue.of(baseCategory3Id))
                .collect(Collectors.toList());
        //2.检索ES获取置顶三级分类（7个）不同置顶三级分类下热度前6个的专辑列表
        //2.1 采用ES检索方法，通过lambda构建请求参数：query,size,aggs
        SearchResponse<AlbumInfoIndex> searchResponse = elasticsearchClient.search(
                s->s.index(INDEX_NAME)
                        .query(q -> q.terms(t -> t.field("category3Id").terms(tf->tf.value(fieldValueList))))
                        .size(0)
                        .aggregations("category3Agg",agg->agg.terms(t->t.field("category3Id").size(10))
                                .aggregations("top6Agg",a1 -> a1.topHits(t -> t.size(6).sort(sort -> sort.field(f -> f.field("hotScore").order(SortOrder.Desc)))))
                        )

                ,AlbumInfoIndex.class);
        //3.解析ES响应聚合
        System.out.println(searchResponse);
        //3.1 获取三级分类聚合结果对象
        Aggregate category3Agg = searchResponse.aggregations().get("category3Agg");
        //3.2 获取三级分类聚合“桶”集合 由于三级分类ID字段类型为Long调用lterms方法
        Buckets<LongTermsBucket> buckets = category3Agg.lterms().buckets();
        List<LongTermsBucket> bucketList = buckets.array();
        if (CollectionUtil.isNotEmpty(bucketList)) {
            //3.3 遍历“桶”集合，每遍历一个“桶”处理某个置顶三级分类热门专辑
            List<Map<String, Object>> listMap = bucketList.stream().map(bucket -> {
                Map<String, Object> map = new HashMap<>();
                //3.3.1 处理热门专辑->分类
                long category3Id = bucket.key();
                BaseCategory3 baseCategory3 = category3Map.get(category3Id);
                map.put("baseCategory3", baseCategory3);
                //3.3.2 处理热门专辑->专辑列表
                //3.3.2.1 继续下钻获取子聚合得到当前分类下热门专辑
                Aggregate top6Agg = bucket.aggregations().get("top6Agg");
                List<Hit<JsonData>> hits = top6Agg.topHits().hits().hits();
                if (CollectionUtil.isNotEmpty(hits)) {
                    List<AlbumInfoIndex> hotAlbumList = hits.stream().map(hit -> {
                        //获取专辑JSON对象类型
                        JsonData source = hit.source();
                        return JSON.parseObject(source.toString(), AlbumInfoIndex.class);
                    }).collect(Collectors.toList());
                    map.put("list", hotAlbumList);
                }
                return map;
            }).collect(Collectors.toList());
            return listMap;
        }

    return null;
    }

    /**
     * 关键字自动补全,1.创建suggestindex并上架 2.转化DSL语句 3.解析查询结果并封装
     * @param keyword
     * @return
     */
    @Override
    @SneakyThrows
    public List<String> completeSuggest(String keyword) {
        // 根据 keyword 创建 DSL 语句
        SearchResponse<SuggestIndex> search = elasticsearchClient.search(s -> s.index(SUGGEST_INDEX_NAME)
                        .suggest(sug -> sug.suggesters("mySuggestKeyword", s1 -> s1.prefix(keyword).completion(c -> c.field("keyword").size(10).skipDuplicates(true)))
                                .suggesters("mySuggestPinyin", s2 -> s2.prefix(keyword).completion(c2 -> c2.field("keywordPinyin").size(10).skipDuplicates(true)))
                                .suggesters("mySuggestSequence", s3 -> s3.prefix(keyword).completion(c3 -> c3.field("keywordSequence").size(10).skipDuplicates(true)))
                        )
                , SuggestIndex.class);
        System.out.println(search.toString());
        //2.解析建议词响应结果，将结果进行去重
        Set<String> hashSet = new HashSet<>();
        hashSet.addAll(this.parseSuggestResult("mySuggestKeyword", search));
        hashSet.addAll(this.parseSuggestResult("mySuggestPinyin", search));
        hashSet.addAll(this.parseSuggestResult("mySuggestSequence", search));
        if (hashSet.size() >= 10) {
            return new ArrayList<>(hashSet).subList(0, 10);
        }
        //3.如果建议词记录数小于10，采用全文查询专辑索引库尝试补全
        SearchResponse<AlbumInfoIndex> response = elasticsearchClient.search(
                s -> s.index(INDEX_NAME).query(q -> q.match(m -> m.field("albumTitle").query(keyword))),
                AlbumInfoIndex.class
        );
        //解析检索结果，将结果放入HashSet
        List<Hit<AlbumInfoIndex>> hits = response.hits().hits();
        if (CollectionUtil.isNotEmpty(hits)) {
            for (Hit<AlbumInfoIndex> hit : hits) {
                AlbumInfoIndex albumInfoIndex = hit.source();
                hashSet.add(albumInfoIndex.getAlbumTitle());
                // 补全10个，超过自动截断
                if (hashSet.size() >= 10) {
                    break;
                }
            }
        }
        //4.最多返回10个自动补全提示词
        return new ArrayList<>(hashSet);

    }
    @Override
    public Collection<String> parseSuggestResult(String suggestName, SearchResponse<SuggestIndex> search) {
        //1.获取指定自定义建议词名称获取建议结果
        List<Suggestion<SuggestIndex>> suggestionList = search.suggest().get(suggestName);
        //2.获取建议自动补全对象
        List<String> list = new ArrayList<>();
        suggestionList.forEach(suggestIndexSuggestion -> {
            //3.获取options中自动补全结果
            for (CompletionSuggestOption<SuggestIndex> suggestOption : suggestIndexSuggestion.completion().options()) {
                SuggestIndex suggestIndex = suggestOption.source();
                list.add(suggestIndex.getTitle());
            }
        });
        return list;
    }

    /**
     * 根据category1Id和dimension查询专辑排行榜数据
     * @param category1Id
     * @param dimension
     * @return
     */
    @Override
    public List<AlbumInfoIndex> findRankingList(Long category1Id, String dimension) {
        String key = RedisConstant.RANKING_KEY_PREFIX + category1Id;
        List<AlbumInfoIndex> albumInfoIndexList = (List<AlbumInfoIndex>) redisTemplate.opsForHash().get(key, dimension);
        if (CollectionUtil.isNotEmpty(albumInfoIndexList)) {
            return albumInfoIndexList;
        }
        return null;
    }

    /**
     * 更新排行榜数据至redis中，理应使用定时器自动刷新排行榜数据
     */
    @Override
    @SneakyThrows
    public void updateLatelyAlbumRanking() {
        // 1.获取所有一级分类
        List<BaseCategory1> baseCategory1s = albumFeignClient.getAllCategory1().getData();
        for (BaseCategory1 baseCategory1 : baseCategory1s) {
            Long baseCategory1Id = baseCategory1.getId();
            // 遍历查询 category1Id(15) <--> dimension(5)
            String[] rankingDimensionArray =
                    new String[]{"hotScore", "playStatNum", "subscribeStatNum", "buyStatNum", "commentStatNum"};
            for (String rankingDimension : rankingDimensionArray) {
                    // 2.创建查询参数(建造者模式创建),并查询结果
                    SearchResponse<AlbumInfoIndex> albumInfoIndexSearchResponse = elasticsearchClient.search(s -> s.index(INDEX_NAME)
                                    .query(q -> q.term(t -> t.field("category1Id").value(baseCategory1Id)))
                                    .size(15)
                                    .sort(s1 -> s1.field(s2 -> s2.field(rankingDimension).order(SortOrder.Desc)))
                            , AlbumInfoIndex.class);
                    // 3.解析ES结果,并存入redis中
                List<Hit<AlbumInfoIndex>> hits = albumInfoIndexSearchResponse.hits().hits();
                String key = RedisConstant.RANKING_KEY_PREFIX + baseCategory1Id;
                if (CollectionUtil.isNotEmpty(hits)){
                    List<AlbumInfoIndex> albumInfoIndexList = hits.stream().map(hit -> hit.source()).collect(Collectors.toList());
                    // 4.保存
                    redisTemplate.opsForHash().put(key, rankingDimension, albumInfoIndexList);
                }
            }
        }

    }


    /**
     * 查询参数转化，注意层级结构
     * @param albumIndexQuery
     * @return
     */
    private SearchRequest queryParams(AlbumIndexQuery albumIndexQuery) {
        // 1.创建查询参数(建造者模式创建) 相当于 第一层"query":{}
        SearchRequest.Builder builder = new SearchRequest.Builder();
        // 2.设置索引
        builder.index(INDEX_NAME);
        // 3.建立最外层bool
        BoolQuery.Builder allBool = new BoolQuery.Builder();
        // 4.关键字判空
        String keyword = albumIndexQuery.getKeyword();
        if(StringUtil.isNotEmpty(keyword)){
            // 4.1 建立内层 bool
            BoolQuery.Builder innerBool = new BoolQuery.Builder();
            innerBool.should(q1 -> q1.match(m -> m.field("albumTitle").query(keyword)));
            innerBool.should(q2 -> q2.match(m -> m.field("albumIntro").query(keyword)));
            innerBool.should(q3 -> q3.term(t -> t.field("announcerName").value(keyword)));
            allBool.must(innerBool.build()._toQuery());
        }
        // 5.一二三级分类判空
        // 5.1 一级分类判空
        if(albumIndexQuery.getCategory1Id() != null ){
            allBool.filter(f -> f.term(t -> t.field("category1Id").value(albumIndexQuery.getCategory1Id())));
        }
        // 5.2 二级分类判空
        if(albumIndexQuery.getCategory2Id() != null ){
            allBool.filter(f -> f.term(t -> t.field("category2Id").value(albumIndexQuery.getCategory2Id())));
        }
        // 5.3 二级分类判空
        if(albumIndexQuery.getCategory3Id() != null ){
            allBool.filter(f -> f.term(t -> t.field("category3Id").value(albumIndexQuery.getCategory3Id())));
        }
        // 6.属性判空
        List<String> attributeList = albumIndexQuery.getAttributeList();
        if(CollectionUtil.isNotEmpty(attributeList)){
            for (String attributeValue : attributeList) {
                // 6.1 获取属性id和属性值id 定义 id:value
                String[] split = attributeValue.split(":");
                // split判空
                if(split != null && split.length == 2){
                    // 6.1.1 创建 nestedQuery
                    NestedQuery.Builder nestedQuery = new NestedQuery.Builder();
                    nestedQuery.path("attributeValueIndexList");
                    // 6.1.2 创建 nestedInnerBool
                    BoolQuery.Builder nestedInnerBool = new BoolQuery.Builder();
                    nestedInnerBool.must(m -> m.term(t -> t.field("attributeValueIndexList.attributeId").value(split[0])));
                    nestedInnerBool.must(m -> m.term(t -> t.field("attributeValueIndexList.valueId").value(split[1])));
                    nestedQuery.query(nestedInnerBool.build()._toQuery());
                    allBool.filter(nestedQuery.build()._toQuery());
                }
            }
        }
        // 封装至外层query
        builder.query(allBool.build()._toQuery());
        // 7.设置排序规则
        String order = albumIndexQuery.getOrder();
        if(StringUtil.isNotBlank(order)){
            String[] split = order.split(":");
            if(split != null && split.length == 2){
                String orderField = "";
                // 存在指令重排风险
                switch (split[0]){
                    case "1":
                        orderField = "hotScore";
                        break;
                    case "2":
                        orderField = "playStatNum";
                        break;
                    case "3":
                        orderField = "createTime";
                        break;
                }
                String finalOrderField = orderField;
                // 7.1 设置排序规则 因与query层级相同
                builder.sort(s -> s.field(f -> f.field(finalOrderField).order("asc".equals(split[1])? SortOrder.Asc: SortOrder.Desc)));
            }
        }
        // 8.设置分页
        int from = (albumIndexQuery.getPageNo() - 1) * albumIndexQuery.getPageSize();
        builder.from(from).size(albumIndexQuery.getPageSize());
        // 9.设置高亮
        builder.highlight(h -> h.fields("albumTitle", hf -> hf.preTags("<font color='red'>").postTags("</font>")));
        // 10.设置结果集
        builder.source(s -> s.filter(f -> f.excludes("category1Id",
                "category2Id",
                "category3Id",
                "attributeValueIndexList.attributeId",
                "attributeValueIndexList.valueId")));

        return builder.build();
    }
    private AlbumSearchResponseVo parseResult(SearchResponse<AlbumInfoIndex> albumInfoIndexSearchResponse, AlbumIndexQuery albumIndexQuery) {
        AlbumSearchResponseVo albumSearchResponseVo = new AlbumSearchResponseVo();
        //封装分页信息（总记录数、总页数、页码、页大小）
        albumSearchResponseVo.setPageNo(albumIndexQuery.getPageNo());
        albumSearchResponseVo.setPageSize(albumIndexQuery.getPageSize());
        // 查询到的总记录数
        long total = albumInfoIndexSearchResponse.hits().total().value();
        albumSearchResponseVo.setTotal(total);
        // 总页数
        albumSearchResponseVo.setTotalPages(total % albumIndexQuery.getPageSize() == 0 ? total / albumIndexQuery.getPageSize() : total / albumIndexQuery.getPageSize() + 1);
        // 将AlbumInfoIndexVo封装至AlbumSearchResponseVo
        List<Hit<AlbumInfoIndex>> hits = albumInfoIndexSearchResponse.hits().hits();
        if(CollectionUtil.isNotEmpty(hits)){
            List<AlbumInfoIndexVo> infoIndexVoList = new ArrayList<>();
            for (Hit<AlbumInfoIndex> hit : hits) {
                AlbumInfoIndexVo infoIndexVo = new AlbumInfoIndexVo();
                BeanUtil.copyProperties(hit.source(), infoIndexVo);
                infoIndexVoList.add(infoIndexVo);
                // 高亮覆盖
                if(hit.highlight() != null && hit.highlight().containsKey("albumTitle")){
                    infoIndexVo.setAlbumTitle(hit.highlight().get("albumTitle").get(0));
                }
            }
            albumSearchResponseVo.setList(infoIndexVoList);
        }
        return albumSearchResponseVo;
    }


}
